import './index.less';
import { useAllCurrentTasks, useExecutionDump } from '@/components/store';
import type { ExecutionTask, ExecutionTaskInsightLocate } from '@midscene/core';
import { typeStr } from '@midscene/core/agent';
import {
  type AnimationScript,
  iconForStatus,
  timeCostStrElement,
} from '@midscene/visualizer';
import { Checkbox, Tag, Tooltip } from 'antd';
import { useEffect } from 'react';
import CameraIcon from '../../icons/camera.svg?react';
import MessageIcon from '../../icons/message.svg?react';
import PlayIcon from '../../icons/play.svg?react';
import type { PlaywrightTasks } from '../../types';
import ReportOverview from '../report-overview';

const SideItem = (props: {
  task: ExecutionTask;
  selected?: boolean;
  onClick?: () => void;
  onItemHover?: (task: ExecutionTask | null, x?: number, y?: number) => any;
  proModeEnabled?: boolean;
}): JSX.Element => {
  const { task, onClick, selected } = props;

  const selectedClass = selected ? 'selected' : '';
  let statusText: JSX.Element | string = task.status;

  const cacheEl =
    task.hitBy?.from === 'Cache' ? (
      <Tag
        style={{
          color: '#1890FF',
          backgroundColor: '#E0F5FF',
          padding: '0 4px',
          marginLeft: '4px',
          marginRight: 0,
          lineHeight: '16px',
        }}
        bordered={false}
      >
        cache
      </Tag>
    ) : null;

  const deepThinkEl = (task as ExecutionTaskInsightLocate)?.log?.dump
    ?.deepThink ? (
    <Tag
      bordered={false}
      style={{
        color: '#722ED1',
        backgroundColor: '#F7EBFF',
        padding: '0 4px',
        marginLeft: '4px',
        marginRight: 0,
        lineHeight: '16px',
      }}
    >
      deepthink
    </Tag>
  ) : null;

  if (task.timing?.cost) {
    statusText = timeCostStrElement(task.timing.cost);
  }

  const statusIcon = (() => {
    const isFinished = task.status === 'finished';
    const isError = isFinished && (task.error || task.errorMessage);

    if (isError) {
      return iconForStatus('failed');
    }

    const isAssertFinishedWithWarning =
      isFinished &&
      task.subType === 'Assert' &&
      task.output === false &&
      task.log.isWaitForAssert;

    if (isAssertFinishedWithWarning) {
      return iconForStatus('finishedWithWarning');
    }

    const isAssertFailed =
      task.subType === 'Assert' && isFinished && task.output === false;

    if (isAssertFailed) {
      return iconForStatus('failed');
    }

    return iconForStatus(task.status);
  })();

  const titleTextIcon =
    task.type === 'Planning' && task.subType !== 'LoadYaml' ? (
      <span
        style={{
          display: 'inline-flex',
          alignItems: 'center',
          marginLeft: '4px',
        }}
      >
        <CameraIcon width={16} height={16} />
      </span>
    ) : null;

  return (
    <div
      className={`side-item ${selectedClass}`}
      onClick={onClick}
      // collect x,y (refer to the body) for hover preview
      onMouseEnter={(event) => {
        const rect = event.currentTarget.getBoundingClientRect();
        const x = rect.left + rect.width;
        const y = rect.top;
        props.onItemHover?.(task, x, y);
      }}
      onMouseLeave={() => {
        props.onItemHover?.(null);
      }}
    >
      {' '}
      <div
        className={`side-item-name ${props.proModeEnabled ? 'pro-mode' : ''}`}
      >
        <span className="status-icon">{statusIcon}</span>
        <div
          className="title"
          style={{ display: 'flex', alignItems: 'center' }}
        >
          {typeStr(task)} {titleTextIcon}
          {cacheEl}
          {deepThinkEl}
        </div>
        <div className="status-text">{statusText}</div>
        {/* Display usage info in table style if available and Pro mode is enabled */}
        {props.proModeEnabled && (
          <>
            <Tooltip title="The name of the model used this time">
              <div className="usage-column model-name">
                {task.usage?.model_name || '-'}
              </div>
            </Tooltip>
            <Tooltip title="Input tokens sent to the AI model">
              <div className="usage-column prompt-tokens">
                {task.usage?.prompt_tokens || '-'}
              </div>
            </Tooltip>
            <Tooltip title="Output tokens generated by the AI model">
              <div className="usage-column completion-tokens">
                {task.usage?.completion_tokens || '-'}
              </div>
            </Tooltip>
          </>
        )}
      </div>
    </div>
  );
};

interface SidebarProps {
  dumps?: PlaywrightTasks[];
  proModeEnabled?: boolean;
  onProModeChange?: (checked: boolean) => void;
  replayAllScripts?: AnimationScript[] | null;
  replayAllMode?: boolean;
  setReplayAllMode?: (mode: boolean) => void;
}

const Sidebar = (props: SidebarProps = {}): JSX.Element => {
  const {
    dumps,
    proModeEnabled = false,
    onProModeChange,
    setReplayAllMode,
  } = props;
  const groupedDump = useExecutionDump((store) => store.dump);
  const setActiveTask = useExecutionDump((store) => store.setActiveTask);
  const activeTask = useExecutionDump((store) => store.activeTask);
  const setHoverTask = useExecutionDump((store) => store.setHoverTask);

  const setHoverPreviewConfig = useExecutionDump(
    (store) => store.setHoverPreviewConfig,
  );
  const allTasks = useAllCurrentTasks();
  const currentSelectedIndex = allTasks?.findIndex(
    (task) => task === activeTask,
  );

  useEffect(() => {
    // all tasks
    const handleKeyDown = (e: KeyboardEvent) => {
      if (!allTasks?.length || allTasks?.length <= 1) {
        return;
      }
      // should be command / ctrl + arrow
      if (e.key === 'ArrowUp' && (e.metaKey || e.ctrlKey)) {
        e.preventDefault();
        const nextIndex = currentSelectedIndex - 1;
        if (nextIndex < 0) {
          return;
        }
        const nextTask = allTasks[nextIndex];
        setActiveTask(nextTask);
      } else if (e.key === 'ArrowDown' && (e.metaKey || e.ctrlKey)) {
        e.preventDefault();
        const nextIndex = currentSelectedIndex + 1;
        if (nextIndex >= allTasks.length) {
          return;
        }
        const nextTask = allTasks[nextIndex];
        setActiveTask(nextTask);
      }
    };
    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [currentSelectedIndex, allTasks, setActiveTask]);

  const sideList = groupedDump ? (
    [groupedDump].map((group, groupIndex) => {
      return (
        <div key={groupIndex}>
          <ReportOverview title={group.groupName} dumps={dumps} />
        </div>
      );
    })
  ) : (
    <span>no tasks</span>
  );

  const totalPromptTokens =
    groupedDump?.executions
      .flatMap((e) => e.tasks)
      .reduce((acc, task) => acc + (task.usage?.prompt_tokens || 0), 0) || 0;

  const totalCompletionTokens =
    groupedDump?.executions
      .flatMap((e) => e.tasks)
      .reduce((acc, task) => acc + (task.usage?.completion_tokens || 0), 0) ||
    0;

  const executionContent = groupedDump ? (
    <div className="execution-info-section">
      <div className="execution-info-title">
        <div className="execution-info-title-left">
          <MessageIcon width={16} height={16} />
          Execution
        </div>
        <div className="execution-info-title-right">
          <Checkbox
            className="token-usage-checkbox"
            checked={proModeEnabled}
            onChange={(e) => onProModeChange?.(e.target.checked)}
          >
            Token usage
          </Checkbox>
        </div>
      </div>
      <div className={`table-header ${proModeEnabled ? 'pro-mode' : ''}`}>
        <div className="header-name">Name</div>
        <div className="header-time">Time</div>
        {proModeEnabled && (
          <>
            <div className="header-model-name">Name</div>
            <div className="header-prompt">Prompt</div>
            <div className="header-completion">Completion</div>
          </>
        )}
      </div>
      <div className="executions-wrapper">
        {groupedDump.executions.map((execution, indexOfExecution) => {
          const { tasks } = execution;
          const taskList = tasks.map((task, index) => {
            return (
              <SideItem
                key={index}
                task={task}
                selected={task === activeTask}
                proModeEnabled={proModeEnabled}
                onClick={() => {
                  setActiveTask(task);
                  setReplayAllMode?.(false);
                }}
                onItemHover={(hoverTask, x, y) => {
                  if (hoverTask && x && y) {
                    setHoverPreviewConfig({ x, y });
                    setHoverTask(hoverTask);
                  } else {
                    setHoverPreviewConfig(null);
                    setHoverTask(null);
                  }
                }}
              />
            );
          });

          return (
            <div key={indexOfExecution}>
              <div className="side-seperator side-seperator-space-up" />
              <div
                className="side-sub-title"
                style={{ display: 'flex', alignItems: 'flex-start' }}
              >
                {execution.name}
              </div>
              <div className="task-list">{taskList}</div>
            </div>
          );
        })}
      </div>
    </div>
  ) : null;

  return (
    <div className="side-bar">
      <div className="page-nav">
        <div className="page-nav-left">
          <div className="page-nav-title">
            Report
            <span className="page-nav-title-hint">
              Switch: Command + Up / Down
            </span>
          </div>
          <div className="page-nav-toolbar">
            <div
              className="icon-button"
              onClick={() => {
                setReplayAllMode?.(true);
              }}
            >
              <PlayIcon />
            </div>
          </div>
        </div>
      </div>
      {sideList}
      {executionContent}
      {proModeEnabled && (
        <>
          <div className="side-seperator side-seperator-line side-seperator-space-up" />
          <div className="task-token-section">
            <div className="task-meta-tokens">
              <div className="token-total-label">Total</div>
              <div className="token-total-item">
                <span className="token-value">{totalPromptTokens}</span>
              </div>
              <div className="token-total-item">
                <span className="token-value">{totalCompletionTokens}</span>
              </div>
            </div>
          </div>
        </>
      )}
    </div>
  );
};

export default Sidebar;
